<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
  <title>保存手机号 - 测试页面</title>
  <style>
    /* 基础样式重置 + 全局变量定义 */
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    :root {
      --primary-color: #2d8cf0;
      --primary-hover: #1e78d6;
      --success-color: #0a8a3f;
      --error-color: #b70000;
      --text-main: #333333;
      --text-secondary: #666666;
      --text-light: #888888;
      --border-normal: #dcdcdc;
      --border-focus: #2d8cf0;
      --bg-main: #f7f7f7;
      --bg-card: #ffffff;
      --shadow-light: 0 2px 8px rgba(0,0,0,0.08);
      --shadow-hover: 0 6px 18px rgba(0,0,0,0.12);
      --radius-normal: 8px;
      --radius-small: 6px;
      --transition-base: all 0.3s ease;
    }

    body {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, "Helvetica Neue", Helvetica, sans-serif;
      background: var(--bg-main);
      padding: 20px;
      min-height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    /* 容器自适应样式 */
    .container {
      width: 100%;
      max-width: 420px;
      background: var(--bg-card);
      padding: 30px 24px;
      border-radius: var(--radius-normal);
      box-shadow: var(--shadow-light);
      transition: var(--transition-base);
    }

    .container:hover {
      box-shadow: var(--shadow-hover);
    }

    /* 标题样式 */
    h1 {
      margin: 0 0 20px;
      font-size: 20px;
      color: var(--text-main);
      font-weight: 600;
      border-left: 4px solid var(--primary-color);
      padding-left: 12px;
    }

    /* 表单元素样式 */
    .form-group {
      margin-bottom: 18px;
    }

    label {
      display: block;
      margin-bottom: 8px;
      font-weight: 500;
      color: var(--text-main);
      font-size: 15px;
    }

    input[type="text"] {
      width: 100%;
      padding: 12px 14px;
      font-size: 15px;
      border: 1px solid var(--border-normal);
      border-radius: var(--radius-small);
      color: var(--text-main);
      transition: var(--transition-base);
      outline: none;
    }

    input[type="text"]::placeholder {
      color: var(--text-light);
      font-size: 14px;
    }

    input[type="text"]:focus {
      border-color: var(--border-focus);
      box-shadow: 0 0 0 3px rgba(45, 140, 240, 0.1);
    }

    input[type="text"]:disabled {
      background-color: #fafafa;
      cursor: not-allowed;
    }

    /* 提示文本样式 */
    .hint {
      font-size: 13px;
      color: var(--text-secondary);
      margin-top: 6px;
      line-height: 1.5;
    }

    /* 错误提示样式 */
    .error {
      color: var(--error-color);
      margin-top: 8px;
      font-size: 13px;
      display: none;
      line-height: 1.5;
      animation: fadeIn 0.3s ease;
    }

    /* 按钮样式 */
    button {
      margin-top: 10px;
      width: 100%;
      padding: 12px;
      font-size: 16px;
      border: none;
      border-radius: var(--radius-small);
      background: var(--primary-color);
      color: white;
      cursor: pointer;
      transition: var(--transition-base);
      font-weight: 500;
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 8px;
    }

    button:disabled {
      background: #a0cfff;
      cursor: not-allowed;
      transform: none;
    }

    button:hover:not(:disabled) {
      background: var(--primary-hover);
      transform: translateY(-2px);
      box-shadow: 0 4px 12px rgba(45, 140, 240, 0.2);
    }

    button:active:not(:disabled) {
      transform: translateY(0);
      box-shadow: 0 2px 8px rgba(45, 140, 240, 0.2);
    }

    /* 结果提示样式 */
    .result {
      margin-top: 16px;
      font-size: 14px;
      line-height: 1.6;
      padding: 10px 12px;
      border-radius: var(--radius-small);
      animation: fadeIn 0.3s ease;
    }

    .success {
      color: var(--success-color);
      background-color: rgba(10, 138, 63, 0.05);
      border: 1px solid rgba(10, 138, 63, 0.2);
    }

    .fail {
      color: var(--error-color);
      background-color: rgba(183, 0, 0, 0.05);
      border: 1px solid rgba(183, 0, 0, 0.2);
    }

    /* 底部小字样式 */
    .small {
      font-size: 12px;
      color: var(--text-light);
      margin-top: 12px;
      line-height: 1.5;
      text-align: left;
    }

    code {
      background-color: #f5f5f5;
      padding: 2px 6px;
      border-radius: 4px;
      font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
      font-size: 11px;
      color: #d73a49;
    }

    /* 动画定义 */
    @keyframes fadeIn {
      from { opacity: 0; transform: translateY(5px); }
      to { opacity: 1; transform: translateY(0); }
    }

    /* 响应式适配：针对小屏设备优化 */
    @media (max-width: 375px) {
      body {
        padding: 15px;
      }

      .container {
        padding: 24px 18px;
      }

      h1 {
        font-size: 18px;
        padding-left: 10px;
      }

      input[type="text"] {
        padding: 11px 12px;
        font-size: 14px;
      }

      button {
        padding: 11px;
        font-size: 15px;
      }

      .small {
        font-size: 11px;
      }
    }

    /* 加载中图标（简化版） */
    .loading-dot {
      display: inline-block;
      width: 8px;
      height: 8px;
      border-radius: 50%;
      background-color: white;
      animation: loading 1.4s infinite ease-in-out both;
    }

    .loading-dot:nth-child(1) {
      animation-delay: -0.32s;
    }

    .loading-dot:nth-child(2) {
      animation-delay: -0.16s;
    }

    @keyframes loading {
      0%, 80%, 100% { transform: scale(0); }
      40% { transform: scale(1); }
    }
	
	/* 输入框容器：用于定位清除按钮 */
	.input-wrapper {
	  position: relative;
	  display: inline-block;
	  width: 100%;
	}

	/* 输入框样式调整（预留按钮位置） */
	#phoneInput {
	  width: 100%;
	  padding-right: 30px; /* 右侧留出按钮位置，避免文字被按钮遮挡 */
	  box-sizing: border-box;
	}

	/* 清除按钮样式 */
	.clear-btn {
	  position: absolute;
	  right: 5px;
	  top: 50%;
	  transform: translateY(-50%);
	  width: 24px;
	  height: 24px;
	  border: none;
	  border-radius: 50%;
	  background: #eee;
	  color: #666;
	  font-size: 16px;
	  line-height: 1;
	  cursor: pointer;
	  display: none; /* 默认隐藏 */
	  padding: 0;
	}

	/* 按钮hover效果 */
	.clear-btn:hover {
	  background: #ddd;
	  color: #333;
	}
  </style>
</head>
<body>
  <div class="container">
    <h1>手机号校验并提交</h1>

    <form id="phoneForm" autocomplete="off">
	<div class="form-group">
	  <label for="phoneInput">请输入手机号</label>
	  <!-- 输入框和清除按钮放在同一个容器里，方便样式控制 -->
	  <div class="input-wrapper">
		<input id="phoneInput" name="phone" type="text" placeholder="例如：13800138000" maxlength="20" />
		<!-- 清除按钮（默认隐藏，有值时显示） -->
		<button type="button" id="clearBtn" class="clear-btn">×</button>
	  </div>
	  <div class="hint">提交前会做格式校验。默认使用中国大陆手机号校验（11位，以1开头）。</div>
	  <div id="error" class="error"></div>
	</div>

      <button id="submitBtn" type="submit">
        提交
      </button>
      
      <div id="result" class="result"></div>
    </form>
  </div>

  <script>
    (function(){
      const form = document.getElementById('phoneForm');
      const phoneInput = document.getElementById('phoneInput');
      const errorEl = document.getElementById('error');
      const submitBtn = document.getElementById('submitBtn');
      const resultEl = document.getElementById('result');

      // 校验规则：默认中国大陆手机号（11位，以1开头，第二位3-9）
      const chinaMobileRegex = /^1[3-9]\d{9}$/;

      // 手机号验证逻辑
      function validate(phone) {
        if (!phone) {
          return '手机号不能为空';
        }
        const trimmed = phone.trim();
        if (!chinaMobileRegex.test(trimmed)) {
          return '手机号格式不正确（请输入中国大陆11位手机号，例如 13800138000）';
        }
        return ''; // 空字符串表示通过
      }

      // 转换为form-urlencoded格式
      function toFormUrlEncoded(obj) {
        return Object.keys(obj).map(k => encodeURIComponent(k) + '=' + encodeURIComponent(obj[k])).join('&');
      }

      // 加载状态处理（添加/移除加载动画）
      function setLoadingState(isLoading) {
        if (isLoading) {
          submitBtn.innerHTML = `
            <span class="loading-dot"></span>
            <span class="loading-dot"></span>
            <span class="loading-dot"></span>
            <span>提交中</span>
          `;
          phoneInput.disabled = true;
        } else {
          submitBtn.innerHTML = '提交';
          phoneInput.disabled = false;
        }
      }

      // 表单提交逻辑
      form.addEventListener('submit', function(evt){
        evt.preventDefault();
        // 重置状态
        errorEl.style.display = 'none';
        resultEl.textContent = '';
        resultEl.className = 'result';
        const phone = phoneInput.value;

        // 前端验证
        const vmsg = validate(phone);
        if (vmsg) {
          errorEl.textContent = vmsg;
          errorEl.style.display = 'block';
          return;
        }

        // 禁用按钮+显示加载状态
        submitBtn.disabled = true;
        setLoadingState(true);

        const url = 'http://liujiji.nat300.top/platformServe/redis/savePhoneAlive';
		//const url = 'http://192.168.1.14:8085/platformServe/redis/savePhoneAlive';

        // 发起POST请求
        fetch(url, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
          },
          body: toFormUrlEncoded({ phone: phone.trim() })
        })
        .then(async response => {
          const text = await response.text();
          // 尝试解析JSON响应
          let parsed = null;
          try { 
            parsed = JSON.parse(text); 
          } catch(e) { 
            parsed = null; 
          }

          // 响应结果判断逻辑
          let isSuccess = false;
          if (parsed === true) {
            isSuccess = true;
          } else if (parsed && typeof parsed === 'object') {
            isSuccess = parsed.success === true || parsed.ok === true;
          } else {
            const trimmedText = text.trim().toLowerCase();
            isSuccess = trimmedText === 'true' || trimmedText === 'success' || trimmedText === 'ok' || (response.ok && trimmedText === '');
          }

          // 显示结果
          if (isSuccess) {
            resultEl.className = 'result success';
            resultEl.innerHTML = '提交成功 ✅ 手机号已保存';
          } else {
            resultEl.className = 'result fail';
            const errorMsg = text ? escapeHtml(text) : `HTTP ${response.status}`;
            resultEl.innerHTML = `提交失败 ❌ 后端返回：${errorMsg}`;
          }
        })
        .catch(err => {
          console.error('请求异常:', err);
          resultEl.className = 'result fail';
          const errorMsg = err?.message ? escapeHtml(err.message) : String(err);
          resultEl.innerHTML = `请求出错 ❌ ${errorMsg}`;
        })
        .finally(() => {
          // 恢复按钮状态
          submitBtn.disabled = false;
          setLoadingState(false);
        });
      });

      // HTML转义处理（防止XSS）
      function escapeHtml(s) {
        return String(s)
          .replace(/&/g, '&amp;')
          .replace(/</g, '&lt;')
          .replace(/>/g, '&gt;')
          .replace(/"/g, '&quot;')
          .replace(/'/g, '&#39;');
      }

      // 输入框聚焦时清除错误提示
      phoneInput.addEventListener('focus', function() {
        errorEl.style.display = 'none';
      });
    })();
	
	// 获取清除按钮元素
	const clearBtn = document.getElementById('clearBtn');

	// 控制清除按钮显示/隐藏
	function toggleClearBtn() {
	  // 当输入框有值时显示按钮，否则隐藏
	  clearBtn.style.display = phoneInput.value.trim() ? 'block' : 'none';
	}

	// 初始检查一次（页面加载时）
	toggleClearBtn();

	// 输入框内容变化时更新按钮显示状态（绑定到input事件）
	phoneInput.addEventListener('input', function() {
	  // 保留之前的空格和86处理逻辑
	  let value = this.value;
	  value = value.replace(/\s+/g, ''); // 清除所有空格
	  value = value.replace(/^\+86/, '').replace(/^86/, ''); // 移除+86/86前缀
	  if (this.value !== value) {
		this.value = value;
	  }
	  
	  // 新增：更新清除按钮显示状态
	  toggleClearBtn();
	});

	// 清除按钮点击事件：清空输入框并隐藏按钮
	clearBtn.addEventListener('click', function() {
	  phoneInput.value = ''; // 清空输入框
	  toggleClearBtn(); // 隐藏按钮
	  errorEl.style.display = 'none'; // 同时清除错误提示
	  phoneInput.focus(); // 聚焦到输入框，方便重新输入
	});

	// 输入框聚焦/失焦时也检查按钮状态（可选，增强体验）
	phoneInput.addEventListener('focus', function() {
	  errorEl.style.display = 'none';
	  toggleClearBtn(); // 聚焦时再检查一次
	});
	phoneInput.addEventListener('blur', toggleClearBtn);
  </script>
</body>
</html>
